/**
 * <b>Pattern class:</b>
 * <hr color=grey size=1>
 *
 * This factory used to create Pattern from xml. It's singlton
 *
 * @author thao
 */
/*
ihelpuoo.regist("ihelpuoo.widget.Pattern");

ihelpuoo.require("ihelpuoo.xml.XMLUtils");
ihelpuoo.require("ihelpuoo.util.Map");
*/
//We use namespace to create such static class. Cause they are no diff in javascript.
ihelpuoo.namespace("widget.pattern");

var ihelpuoo_widget_patterns = ihelpuoo.util.map();
/**
 * @method
 * create a HtmlSegment instance by the url
 * @param {String} url
 * @return {HtmlSegment} htmlSegment instance or null if not found by url
 */
ihelpuoo.widget.pattern.create = function(name)
{
	var content =  ihelpuoo_widget_patterns.get(name);
	if(null==content)
	{
		var url = ihelpuoo.http.server().url("eve","getPattern","patternName="+name,false);
		var content = ihelpuoo.http.GETXML(url);
		if(null!=content)
			ihelpuoo_widget_patterns.put(name,content);
	}
	if(content)
		return new ihelpuoo.widget.Pattern(content);
	return null;
}

/**
 * @constructor ihelpuoo.widget.Pattern
 * @class
 * @classDescription Constractor of HtmlSegment
 * @param {Node} xml
 */
ihelpuoo.widget.Pattern = function(xml){
	this.xml = xml.documentElement;
	this.segmentXml = null;
	this.pathsXml = null;
	this.pathMap = new ihelpuoo.util.Map();
	this.domNodes = new Array();
	this.segmentXml = ihelpuoo.xml.selectNodes(this.xml,"/SegmentRoot/Nodes")[0];
	this.pathsXml = ihelpuoo.xml.selectNodes(this.xml,"/SegmentRoot/Paths")[0];
	//remember paths in segmentXml for latter use
	this.parsePaths();
    //build the html dom and map the paths
	this.buildDom();
}

ihelpuoo.widget.Pattern.prototype
=
{
	keys: function()
	{
		if(!this.pathMap)return new Array();
		return this.pathMap.keys();
	},
	
	/**
	 * @method parsePaths
	 * set paths into segmentXml nodes
	 */
	parsePaths: function ()
	{
		var paths = ihelpuoo.xml.selectNodes(this.pathsXml,"./Path");
		for(var i = 0; i < paths.length; i++){
			var path = paths[i].childNodes[0].nodeValue
			var key = paths[i].attributes.getNamedItem("key").value;
			
			if(ihelpuoo.isTraceEnabled())
				ihelpuoo.trace("set node:" + path);
			
			var segNode = ihelpuoo.xml.selectNodes(this.segmentXml,path)[0];
			
			if(null==segNode)
				ihelpuoo.error("Fail to match path: " + path);
				
			this.addKeyToNode(segNode, key);
		}
	},
	
	/**
	 * @method addKeyToNode
	 * @param {Node} node
	 * @param {String} key
	 */
	addKeyToNode: function (node, key)
	{
		var keys = node.getAttribute("_keys");
		
		if(keys == null || keys == ""){
			keys = key;
		}else{
			keys = keys + ";" + key;
		}
		node.setAttribute("_keys",keys);
	},
	
	/**
	 * @method getDomNodes
	 * @return {Array} dom nodes array
	 */
	getDomNodes: function ()
	{
		return this.domNodes;
	},
	
	/**
	 * @method registKeys
	 * @param {String} keys
	 * @param {Node} node
	 */
	registKeys: function (keys, node)
	{
		var key = null;
		var keyList = keys.split(";");
		for(key in keyList){
			this.pathMap.put(keyList[key],node);
		}
	},
	
	/**
	 * @method getElementByPathkey
	 * @param {String} key
	 */
	getElementByPathkey: function (key)
	{
		return this.pathMap.get(key);
	},
	
	/**
	 * @method buildDom
	 * build the dom nodes
	 */
	buildDom: function ()
	{
		if(ihelpuoo.isTraceEnabled())
			ihelpuoo.trace("buildDom....");
		
		var childNodes = this.segmentXml.childNodes;
		var tempNode = null;
		var keys = null;
		for(var i = 0; i < childNodes.length; i++)
		{
			tempNode = ihelpuoo.xml.transformElement(childNodes[i]);
			if(null==tempNode)continue;
			
			if(ihelpuoo.isTraceEnabled())
				ihelpuoo.trace(" + " + childNodes[i].nodeName);
			
			this.domNodes.push(tempNode);
			if(childNodes[i].nodeType == Node.ELEMENT_NODE){
				keys = childNodes[i].getAttribute("_keys");
			}else{
				keys = null;
			}
			if(keys){
				this.registKeys(keys, tempNode);
			}
			if(childNodes[i].nodeType == Node.ELEMENT_NODE && childNodes[i].nodeName != "script"){
				this.buildSubDom(tempNode, childNodes[i].childNodes);
			}
		}
	},
	
	/**
	 * @method buildSubDom
	 * @param {Element} dom parent element
	 * @param {Array} xml child nodes
	 * build the dom nodes
	 */
	buildSubDom: function (parent, children)
	{
		var childNodes = children;
		var tempNode = null;
		var keys = null;
		for(var i = 0; i < childNodes.length; i++)
		{
			if(parent.tagName=="TABLE" && childNodes[i].nodeName=="tr")
			{
				if(ihelpuoo.isTraceEnabled()) ihelpuoo.trace(" TR for TABLE");
				tempNode = ihelpuoo.dom.insertRow(parent);
				ihelpuoo.xml.attachAttributeByList(tempNode,childNodes[i].attributes);
			}
			else if(parent.tagName=="TR" && childNodes[i].nodeName=="td")
			{
				if(ihelpuoo.isTraceEnabled()) ihelpuoo.trace(" TD for TR");
				tempNode = ihelpuoo.dom.insertCell(parent);
				ihelpuoo.xml.attachAttributeByList(tempNode,childNodes[i].attributes);
			}
			else
			{
				if(ihelpuoo.isTraceEnabled()) ihelpuoo.trace(" NORMAL ");
				tempNode = ihelpuoo.xml.transformElement(childNodes[i]);
				if(null!=tempNode)
					parent.appendChild(tempNode);
			}
			if(null==tempNode)continue;
			if(ihelpuoo.isTraceEnabled())
				ihelpuoo.trace(" [" + parent.tagName + "] + " + childNodes[i].nodeName);			
			if(childNodes[i].nodeType == Node.ELEMENT_NODE)
			{
				keys = childNodes[i].getAttribute("_keys");
			}
			else
			{
				keys = null;
			}
			if(keys)
			{
				this.registKeys(keys, tempNode);
			}
			if(childNodes[i].nodeType == Node.ELEMENT_NODE && childNodes[i].node != "script")
			{
				this.buildSubDom(tempNode, childNodes[i].childNodes);
			}
		}
	},
	
	/**
	 * @method attachTo
	 * @param {Element} parent dom element
	 */
	attachTo: function(parent)
	{
		if(!parent)
		{
			ihelpuoo.warn("Pattern can not be attach to NULL!");
			return;
		}
		for(var i = 0; i < this.domNodes.length; i++){
			parent.appendChild(this.domNodes[i]);
		}
	},
	
	/**
	 * @method setContent
	 * @param {String} key
	 * @param {String} innerHtml
	 */
	setContent: function(key, innerHtml)
	{
		var ele = this.getElementByPathkey(key);
		ele.innerHTML = innerHtml;
	},
	
	/**
	 * @method insertChild
	 * @param {String} key
	 * @param {Element} ele
	 */
	insertChild: function(key, element)
	{
		var ele = this.getElementByPathkey(key);
		ele.appendChild(element);
	},

	/**
	 * @method insertChildren
	 * @param {String} key
	 * @param {Array} doms
	 */
	insertChildren: function(key, doms)
	{
		var ele = this.getElementByPathkey(key);
		for(var i = 0; i < doms.length; i++){
			ele.appendChild(doms[i]);
		}
	},

	/**
	 * @method cleanChildren
	 * @param {String} key
	 */
	clear: function(key)
	{
		var ele = this.getElementByPathkey(key);
		ele.innerHTML = "";
	}
	
	,
	/**
	 * Fill current pattern all key by a JavaScript object.
	 * the object's attribute (type is not function) will be fill to the same name 
	 * key whole.
	 * 
	 * @param {Object} data
	 */
	fillByObject: function(obj)
	{
		if(null==obj) return;
		for(var key in obj)
		{
			var ele = this.getElementByPathkey(key);
			if(null==ele) continue;
			var v = obj[key];
			if("function"!=(typeof v))
				ihelpuoo.dom.autoSetObject(ele,v);
		}
	}
}